#pragma once
#ifndef __LIT__FLAGS__INCLUDED__HH__
#define __LIT__FLAGS__INCLUDED__HH__

#include <LitPrerequisites.h>

namespace Lit
{
	template<typename EnumT, typename flag_holder = unsigned long>
	class LIT_API_EXPORT_ONLY Flags
	{
		flag_holder f;
	public:
		typedef EnumT Enum;
	
		Flags( Enum val ) : f( val ){}
		Flags( const flag_holder &flags ) : f( flags ){}
		Flags( const Flags<Enum,flag_holder>& rk ) : f(rk.f){}
		Flags( ) : f(flag_holder(0)){}
		~Flags(){}
		
		const flag_holder& flags() const{ return f; }

		Flags<Enum>& operator=( const Flags<Enum,flag_holder>& rk ){ f = rk.f; return *this; }
		Flags<Enum>& operator=( flag_holder rk ){ f = rk; return *this; }
		Flags<Enum>& operator=( Enum rk ){ f=0; return add(rk); }
	
		bool operator==( const Flags<Enum,flag_holder>& rk ) const{ return f==rk.f; }
		bool operator!=( const Flags<Enum,flag_holder>& rk ) const{ return f!=rk.f; }

		bool operator==( size_t rk ) const{ return f==rk.f; }
		bool operator!=( size_t rk ) const{ return f!=rk.f; }

		bool operator&(Enum flag) const{ return test(flag); }
		Flags<Enum> operator|( Enum flag ) const{ return Flags<Enum,flag_holder>( f | flag ); }
		Flags<Enum> operator~( ) const{ return ~f; }
		Flags<Enum> operator^( Enum flag ) const{ return Flags<Enum,flag_holder>( f ^ flag ); }

		Flags<Enum,flag_holder>& operator|=( Enum flag ){ return add(flag); }
		Flags<Enum,flag_holder>& operator^=( Enum flag ){ return toggle(flag); }

		Flags<Enum,flag_holder>& operator<<( Enum flag ){ return add( flag ); }
	
		bool test( Enum flag ) const{ return ((f&flag)!=0); }
		Flags<Enum,flag_holder>& add( Enum flag ){ f |= flag; return *this; }
		Flags<Enum,flag_holder>& remove( Enum flag ){ f &= ~flag; return *this; }
		Flags<Enum,flag_holder>& toggle( Enum flag ){ f ^= flag; return *this; }
	};
};
#endif